﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GDISim._Infrastructure._Hardware._Datacenter;
using GDISim._Input;
using GDISim._Infrastructure._Software._Application;
using GDISim._Infrastructure._Software._Job;
using GDISim._Infrastructure._Software._Data;

namespace GDISim._Infrastructure
{
    public class Infrastructure
    {
        #region Members
        private string infrastructureFilename;
        private List<string> workloadFilenameList;
        private List<string> applicationFilenameList;
        private List<string> jobFrequencyFilenameList;
        private List<string> jobFilenameList;
        private string dataOwnershipFilename;
        private string dataGrowthFilename;
        private List<Datacenter> datacenterList;
        private List<Application> applicationList;
        private List<Job> jobList;
        private TimeSpan simStartTime;
        private TimeSpan simStopTime;
        private TimeSpan interval;
        private string outputFileName;
        #endregion

        #region Constructor
        private Infrastructure() { }
        public static Infrastructure GlobalInfrastructure = new Infrastructure();

        static Infrastructure()
        {
            Infrastructure.GlobalInfrastructure.datacenterList = new List<Datacenter>();
            Infrastructure.GlobalInfrastructure.workloadFilenameList = new List<string>();
            Infrastructure.GlobalInfrastructure.applicationFilenameList = new List<string>();
            Infrastructure.GlobalInfrastructure.jobFrequencyFilenameList = new List<string>();
            Infrastructure.GlobalInfrastructure.jobFilenameList = new List<string>();
            Infrastructure.GlobalInfrastructure.applicationList= new List<Application>();
            Infrastructure.GlobalInfrastructure.jobList = new List<Job>();
        }
        #endregion

        #region Properties
        public string InfrastructureFilename
        {
            get
            {
                return this.infrastructureFilename;
            }
            set
            {
                this.infrastructureFilename = value;
            }
        }
        public List<string> WorkloadFilenameList
        {
            get
            {
                return this.workloadFilenameList;
            }
            set
            {
                this.workloadFilenameList = value;
            }
        }
        public List<string> ApplicationFilenameList
        {
            get
            {
                return this.applicationFilenameList;
            }
            set
            {
                this.applicationFilenameList = value;
            }
        }
        public List<string> JobfrequencyFilenameList
        {
            get
            {
                return this.jobFrequencyFilenameList;
            }
            set
            {
                this.jobFrequencyFilenameList = value;
            }
        }
        public List<string> JobFilenameList
        {
            get
            {
                return this.jobFilenameList;
            }
            set
            {
                this.jobFilenameList = value;
            }
        }
        public string DataOwnershipFilename
        {
            get
            {
                return this.dataOwnershipFilename;
            }
            set
            {
                this.dataOwnershipFilename = value;
            }
        }
        public string DataOwnerGrowthFilename
        {
            get
            {
                return this.dataGrowthFilename;
            }
            set
            {
                this.dataGrowthFilename = value;
            }
        }
        public List<Datacenter> DatacenterList
        {
            get
            {
                return this.datacenterList;
            }
            set
            {
                this.datacenterList = value;
            }
        }
        public List<Application> ApplicationList
        {
            get
            {
                return this.applicationList;
            }
            set
            {
                this.applicationList = value;
            }
        }
        public List<Job> JobList
        {
            get
            {
                return this.jobList;
            }
            set
            {
                this.jobList = value;
            }
        }
        public TimeSpan SimStartTime
        {
            get
            {
                return this.simStartTime;
            }
            set
            {
                this.simStartTime = value;
            }
        }
        public TimeSpan SimStopTime
        {
            get
            {
                return this.simStopTime;
            }
            set
            {
                this.simStopTime = value;
            }
        }
        public TimeSpan Interval
        {
            get
            {
                return this.interval;
            }
            set
            {
                this.interval = value;
            }
        }
        public string OutputFileName
        {
            get
            {
                return this.outputFileName;
            }
            set
            {
                this.outputFileName = value;
            }
        }
        #endregion

        #region Methods
        public void CreateInfrastructure(string infrastructureFilename)
        {
            this.infrastructureFilename = infrastructureFilename;
            this.datacenterList = Xml.DeserializeListFromXML<Datacenter>(this.infrastructureFilename);
        }
        public void AddApplicationWorkload(string workloadFilename)
        {
            this.workloadFilenameList.Add(workloadFilename);
            List<Workload> workloadList = Xml.DeserializeListFromXML<Workload>(workloadFilename);

            foreach (Workload w in workloadList)
            {
                datacenterList.Find(dc => dc.Name == w.DcName).WorkloadList.Add(w);
            }
        }
        public void AddApplicationDefinition(string applicationFilename)
        {
            this.applicationFilenameList.Add(applicationFilename);
            Application app = Xml.DeserializeFromXML<Application>(applicationFilename);
            Infrastructure.GlobalInfrastructure.applicationList.Add(app);
        }
        public void AddJobFrequency(string jobfrequencyFilename)
        {
            this.jobFrequencyFilenameList.Add(jobfrequencyFilename);
            List<JobFrequency> jobfrequencyList = Xml.DeserializeListFromXML<JobFrequency>(jobfrequencyFilename);

            foreach (JobFrequency jf in jobfrequencyList)
            {
                datacenterList.Find(dc => dc.Name == jf.DcName).JobFrequencyList.Add(jf);
            }
        }
        public void AddJobDefinition(string jobFilename)
        {
            this.jobFilenameList.Add(jobFilename);
            Job job = Xml.DeserializeFromXML<Job>(jobFilename);
            Infrastructure.GlobalInfrastructure.jobList.Add(job);

        }
        public void AddDataOwnership(string dataOwnershipFilename)
        {
            this.dataOwnershipFilename=dataOwnershipFilename;
            List<DataOwnership> dataOwnershipList = Xml.DeserializeListFromXML<DataOwnership>(dataOwnershipFilename);

            foreach (DataOwnership dow in dataOwnershipList)
            {
                datacenterList.Find(dc => dc.Name == dow.DcName).DataOwnership = dow;
            }
        }
        public void AddDataGrowth(string dataGrowthFilename)
        {
            this.dataGrowthFilename = dataGrowthFilename;
            List<DataGrowth> dataGrowthList = Xml.DeserializeListFromXML<DataGrowth>(dataGrowthFilename);

            foreach (DataGrowth dg in dataGrowthList)
            {
                datacenterList.Find(dc => dc.Name == dg.DcName).DataGrowth = dg;
            }
        }
        public void StartSimulation(TimeSpan simStartTime, TimeSpan simStopTime, TimeSpan interval, string outputFileName)
        {
            datacenterList.ForEach(dc => dc.GenerateDatacenterOperationRequestList());
        }
            

        #endregion
    }
}
